//
// Created by 郝羽 on 2018/5/14.
//

#include "rtp.hpp"

#include "xcutil.h"

uint16_t rtp_get_seq(unsigned char *buf, int len) {
    return be_get_u16(buf + 2);
}

void rtp_set_seq(unsigned char* buf, int len, uint16_t seq) {
    be_set_u16(seq, buf + 2);
}

bool rtp_get_p(unsigned char *buf, int len) {
    return ((buf[0] >> 5) & 0x1) == 1;
}

void rtp_set_p(unsigned char* buf, int len, bool p) {
    buf[0] &= (255 - (1 << 5));
    buf[0] |= (p ? 1 : 0) << 5;
}

bool rtp_get_x(unsigned char* buf, int len) {
    return buf[0] >> 4 & 1;
}

void rtp_set_x(unsigned char* buf, int len, bool x) {
    buf[0] &= (255 - (1 << 4));
    buf[0] |= (x ? 1 : 0) << 4;
}

uint8_t rtp_get_cc(unsigned char* buf, int len) {
    return uint8_t(buf[0] & 0x0f);
}

void rtp_set_cc(unsigned char* buf, int len, uint8_t cc) {
    buf[0] &= (255 - 8 - 4 - 2 - 1);
    buf[0] |= cc;
}

uint32_t rtcp_get_ssrc(const unsigned char *buf, int size) {
    if (size <= 4){
        return 0;
    }

    const unsigned char * rtcp = buf;
    int total = size;
    while(rtcp) {
        unsigned char v =  (rtcp[0]>>6) & 0x3;
        unsigned char pt = (rtcp[1]>>0) & 0xFF;
        unsigned short plen = be_get_u16(rtcp+2); // packet length in 4bytes minus 1

        if(v != 2){
            return 0;
        }

        if(pt == 200 || pt == 201 || pt == 205 || pt == 206){
            unsigned int ssrc = be_get_u32(rtcp+4);
            return ssrc;
        }

        total -= plen*4+4;
        if(total <= 4) {
            return 0;
        }
        rtcp = (const unsigned char *)((uint32_t*)rtcp + plen + 1);
    }
    return 0;
}

uint32_t rtp_get_ssrc(const unsigned char* buf, int size) {
    if (size < 12) {
        return 0;
    }
    auto ssrc = be_get_u32(buf + 8);
    return ssrc;
}

void rtp_set_ssrc(unsigned char *buf, int size, uint32_t ssrc) {
    if (size < 12) {
        return;
    }
    be_set_u32(ssrc, buf + 8);
    return;
}

uint8_t rtp_get_pt(const unsigned char* buf, int size) {
    if (size < 12) {
        return 255;
    }
    auto pt = buf[1] & 0x7f;
    return pt;
}


bool is_rtcp(const unsigned char* data, int len) {
    char pt = data[1] & 0x7F;
    return (63 < pt) && (pt < 96);
}